
using Avalonia.Logging;

using Bee.Base.Abstractions;
using Bee.Base.Abstractions.Tasks;
using Bee.Base.Models.Tasks;
using Bee.Plugin.Multimedia.Models;

using FFMpegCore;
using FFMpegCore.Enums;

using Ke.Bee.Localization.Localizer.Abstractions;

using LanguageExt;

using Microsoft.Extensions.Logging;

namespace Bee.Plugin.Multimedia.Tasks;

public class AudioProcessTaskHandler(ICoverHandler coverHandler, ILocalizer localizer, ILogger<AudioProcessTaskHandler> logger) :
    TaskHandlerBase<AudioProcessArguments>(coverHandler)
{
    private readonly ILocalizer _l = localizer;
    private readonly ILogger<AudioProcessTaskHandler> _logger = logger;

    private Fin<Unit> GetExecutionFailedMessage(string fileName) => Fin<Unit>.Fail($"{_l["Task.Execution.Failed"]}, {fileName}");

    public override async Task<Fin<Unit>> ExecuteAsync(TaskItem taskItem,
        AudioProcessArguments arguments,
        Action<double> progressCallback,
        CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        // 分析原视频信息
        var analysis = FFProbe.Analyse(taskItem.Input);

        var fileName = Path.GetFileNameWithoutExtension(taskItem.Input);

        // 输出文件
        var outputFile = Path.Combine(arguments.OutputDirectory,
            $"{fileName}.{arguments.OutputFormat}")
            ;

        try
        {
            await FFMpegArguments.FromFileInput(taskItem.Input)
                .OutputToFile(outputFile, arguments.Overwrite, ffArgs =>
                {
                    // 采样率
                    ffArgs.WithAudioSamplingRate(arguments.SamplingRate);
                    // 比特率
                    ffArgs.WithAudioBitrate(arguments.Bitrate);

                    // 设置编码器
                    var codecIndex = arguments.AudioCodecIndex ?? 0;
                    if (codecIndex > 0)
                    {
                        ffArgs.WithAudioCodec(MultimediaProcessConsts.AvailableAudioCodecs[codecIndex].Name);
                    }

                    // 强制指定输出格式
                    if (arguments.ForceFormat)
                    {
                        ffArgs.ForceFormat(arguments.OutputFormat);
                    }

                    // 输出通道数
                    if (arguments.NumChannels > 0)
                    {
                        ffArgs.WithCustomArgument($"-ac {arguments.NumChannels}");
                    }
                })
                .NotifyOnProgress(progressCallback, analysis.Duration)
                .ProcessAsynchronously()
                ;

            progressCallback(100);

            //return await Task.FromResult(r ? Fin<Unit>.Succ(Unit.Default) : GetExecutionFailedMessage(fileName));
            return Fin<Unit>.Succ(Unit.Default);
        }
        catch (Exception e)
        {
            _logger.LogError(e, e.Message);
            return GetExecutionFailedMessage(fileName);
        }
    }
}